import 'dart:convert';
import 'dart:developer';
import 'dart:convert' as convert;
import 'package:dio/dio.dart';
import 'package:guochaoapp/config/config.dart';
import 'package:guochaoapp/generated/json/base/json_convert_content.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:encrypt/encrypt.dart';

enum Method {
  GET,
  POST,
  PUT,
  DELETE
}

typedef SuccessCallBack<T> = Future Function(Map map, T model);
typedef FaildCallBack<T> = Future Function(T t);

class HttpClient {

  static Future<String> decodeString(String content) async{
    var privateKeyStr = await rootBundle.loadString('assets/data/rsa_private_key.pem');
    var privateKey =  RSAKeyParser().parse(privateKeyStr);
    final decrypter = Encrypter(RSA(privateKey: privateKey));
    return await decrypter.decrypt(Encrypted.fromBase64(content));
  }

  GCConfig _config;
  Dio _client;

  GCConfig get config => _config;

  Dio get client => _client;

  static HttpClient _instance;

  static HttpClient get instance => _getInstance();

  factory HttpClient([GCConfig config, Dio client]) =>
      _getInstance(config: config, client: client);

  HttpClient._internal(GCConfig config, Dio client) {
    //初始化
    _config = config;
    _client = client;
    _client.options.baseUrl = _config.apiBaseUrl;
  }

  static HttpClient _getInstance({GCConfig config, Dio client}) {
    if (_instance == null) {
      _instance = HttpClient._internal(config, client);
    }
    return _instance;
  }

  Map getCommonHttpHeader() {
    Map<String, dynamic> login_headers = {};
    Map<String, dynamic> dio_headers = {
      "appver": 'ios_' + _config.packageInfo.version
    };

    //添加公共参数
//    UserEntity userEntity = GCContainer.instance.userEntity;
//
//    if (userEntity != null) {
//      String uid_token = userEntity.reply.uid + ':' +
//          userEntity.reply.authToken;
//
//      String Authorization = 'Basic ' + uid_token.encodeBase64();
//      login_headers.addAll({
//        'Authorization': Authorization,
////          'deviceid' '1': , //先判断是安卓还是iOS 在用deiveinfoplugin 获取对应平台的id
//        'user_Id': userEntity == null ? '' : userEntity.reply.uid,
//        'user_token': userEntity == null ? '' : userEntity.reply.authToken,
//      });
//    }

    dio_headers.addAll(login_headers);
    return dio_headers;
  }

  static Future<void> request<T>({
    String url,
    Method method = Method.POST,
    Map<String, dynamic> params,
    Map<String, dynamic> data,
    Map<String, String> header,
    bool autoToastErrorMessage = false,
    SuccessCallBack<T> onSuccess,
    FaildCallBack<String> onFailed,
    VoidCallback onCompleted,
  }) async {
    // TODO: implement request

    try {
      Response response;

      Dio _client = HttpClient.instance.client;
      //打印请求信息
      log('request URL :' + _client.options.baseUrl + url);
      log('request params :' + params.toString());
      log('request data :' + data.toString());
      log('request header :' + _client.options.headers.toString());

      //处理请求头
      Map requestHeader = HttpClient.instance.getCommonHttpHeader();
      if(header != null && header.length > 0)
        requestHeader.addAll(header);
      _client.options.headers = requestHeader;

      switch(method) {
        case Method.GET:
          response = await _client.get(url, queryParameters: params);
          break;
        case Method.POST:
          response = await _client.post(url,data: data);
          break;
        case Method.PUT:
          response = await _client.put(url, queryParameters: params, data: data);
          break;
        case Method.DELETE:
          response = await _client.delete(url, queryParameters: params, data: data);
          break;
        default:
          break;
      }

      log(response.data.toString());
//      log(response.headers.toString());
//      log(response.request.toString());
//       log(response.statusCode.toString());

      if (response.statusCode == 200) {

        Map json_data;
        if(response.data is String) {
          json_data = convert.jsonDecode(response.data);
        } else if(response.data is Map) {
          Map<String, dynamic> resMap = response.data;
          if(response.data['sign'] != null) {
            decodeString(response.data['sign']).then((String res) {
              final key = Key.fromUtf8(res);
              final encrypter = Encrypter(AES(key, mode: AESMode.ecb));
              final decrypted = encrypter.decrypt64(response.data['data']);
              resMap["data"] = json.decode(decrypted);
              json_data = resMap;

              print("=========");
              print(json_data);

              var model = JsonConvert.fromJsonAsT<T>(json_data);

              if(json_data['code'] == 200 && json_data['success']) {
                if (onSuccess != null) onSuccess(json_data, model);
              } else {
//          if(autoToastErrorMessage) GCContainer.showMessage(text: json_data['msg']);
                if (onFailed != null) onFailed(json_data['msg']);
              }

              if (onCompleted != null) onCompleted();
              // if (onSuccess != null) onSuccess(result != null ? result : json_data, json_data);
            });
          } else {
            json_data = resMap;
            var model = JsonConvert.fromJsonAsT<T>(json_data);

            if(json_data['code'] == 200 && json_data['success']) {
              if (onSuccess != null) onSuccess(json_data, model);
            } else {
//          if(autoToastErrorMessage) GCContainer.showMessage(text: json_data['msg']);
              if (onFailed != null) onFailed(json_data['msg']);
            }

            if (onCompleted != null) onCompleted();
          }

        }

      } else {
        if (onCompleted != null) onCompleted();
        throw Exception('statusCode: ${response.statusCode}');
      }
    } on DioError catch (e, s) {
      log('request error: ' + e.toString());
      log('request error strack' + s.toString());
      if (onCompleted != null) onCompleted();
      if (onFailed != null) onFailed(e.toString());
//      if(autoToastErrorMessage) GCContainer.showMessage(text: e.toString());
    }
  }

  //处理返回结果
  //返回值决定了 是否将结果回调出去
//  static bool _handleResponseWithResult(Map map) {
//    if(map == null) return true;
//
//    String code = map['code'];
//
//    switch (code) {
//      case '999':
//      //请求成功
//        return true;
//        break;
//      case '1000':
//        break;
//      case '1003':
//        return false;
//      default:
//        return true;
//        break;
//    }
//
//    return true;
//  }

}